package com.zzz.common.security.handler;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.zzz.common.core.domain.R;
import com.zzz.common.core.enums.ResultCode;
import com.zzz.common.security.exception.ControllerException;
import com.zzz.common.security.exception.ServiceException;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.Collection;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @BelongsProject: oj-project
 * @BelongsPackage: com.zzz.common.security
 * @Author: zhai
 * @CreateTime: 2025-09-22  09:41
 * @Description: TODO 全局异常处理器
 * @Version: 1.0
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler extends RuntimeException {
    /**
     * 请求⽅式不⽀持
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public R<?> handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e,
                                                    HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        return R.fail(ResultCode.ERROR);
    }
    /**
     * 拦截运⾏时异常
     */
    @ExceptionHandler(RuntimeException.class)
    public R<?> handleRuntimeException(RuntimeException e, HttpServletRequest
            request) {
        String requestURI = request.getRequestURI();
        return R.fail(ResultCode.ERROR);
    }
    /**
     * 系统异常
     */
    @ExceptionHandler(Exception.class)
    public R<?> handleException(Exception e, HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        return R.fail(ResultCode.ERROR);
    }

    /**
     * @description: 参数校验异常(validation)
     * @author: zhai
     * @date: 2025/9/23 21:03
     * @param: [e]
     * @return: com.zzz.common.core.domain.R<java.lang.Void>
     **/
    @ExceptionHandler(BindException.class)
    public R<Void> handleBindException(BindException e) {
        log.error(e.getMessage());
        String message = join(
                e.getAllErrors(),
                DefaultMessageSourceResolvable::getDefaultMessage,
                ", "
        );
        return R.fail(ResultCode.FAILED_PARAMS_VALIDATE.getCode(), message);
    }

    private <E> String join(Collection<E> collection, Function<E, String> function, CharSequence delimiter) {
        if (CollUtil.isEmpty(collection)) {
            return StrUtil.EMPTY;
        }
        return collection.stream()
                .map(function)
                .filter(Objects::nonNull)
                .collect(Collectors.joining(delimiter));
    }


    /**
     * @description: 自定义服务层异常管理
     * @author: zhai
     * @date: 2025/10/13 13:30
     * @param: [e]
     * @return: com.zzz.common.core.domain.R<java.lang.Void>
     **/
    @ExceptionHandler
    public R<?> serviceException(ServiceException e, HttpServletRequest request) {
        String requestURL = request.getRequestURI();
        ResultCode resultCode = e.getResultCode();
        log.error("在请求路径：【{}】，发生异常",requestURL,e);
        return R.fail(resultCode);
    }

    /**
     * @description: 自定义控制器层异常管理
     * @author: zhai
     * @date: 2025/10/13 13:30
     * @param: [e]
     * @return: com.zzz.common.core.domain.R<java.lang.Void>
     **/
    @ExceptionHandler
    public R<?> controllerException(ControllerException e, HttpServletRequest request) {
        String requestURL = request.getRequestURI();
        ResultCode resultCode = e.getResultCode();
        log.error("在请求路径：【{}】，发生异常",requestURL,e);
        return R.fail(resultCode);
    }
}
